package com.tools.web.interceptor.auth;

import com.tools.common.object.Note;
import com.tools.common.thread.TimePair;
import com.tools.common.thread.Timeunit;

import java.util.Objects;

/**
 * token 续期方案实体类
 * 必须满足所有的 [必须条件] 才能开启续期。
 * maxAllowExtendTime 和 maxAllowCount 有一个有效都算一个必须条件
 * */
@Note("token 续期方案实体类。" +
        "必须满足所有的 [必须条件] 才能开启续期。" +
        "maxAllowExtendTime 和 maxAllowCount 有一个有效都算一个必须条件")
public final class TokenExtender {

    @Note("[必须条件 1]：是否开启 token 续期。默认关闭")
    private boolean enableExtend;

    @Note("[必须条件 2]：token 每次续期续多长时间。" +
            "【为 null、 0、负数都不开启】")
    private TimePair extendTime;

    @Note("从登录后的时间开始到这个时间点之内过期的 token 都允许续期。" +
            "【为 null、 0、负数都不开启】。" +
            "若和 maxAllowCount 一起使用的话，该时间的优先级最高。")
    private TimePair maxAllowExtendTime;

    @Note("从登录后的时间开始，可以允许 token 续期多少次。" +
            "【为 null、 0、负数都不开启】。" +
            "若和 maxAllowExtendTime 一起使用的话，" +
            "则是：【在 maxAllowExtendTime 的时间内允许续期 maxAllowCount 次】")
    private int maxAllowCount;

    @Note("若过期时间临界点 - 现在 <= 该值，那就执行续期（必须大于 0 才生效）")
    private TimePair minExtendThresholdTime;

    /* **************************************************************************************
     *
     *          构造器
     *
     * **************************************************************************************
     * */

    public TokenExtender() {}
    
    public static TokenExtender of() {
        return new TokenExtender();
    }

    /* **************************************************************************************
     *
     *          Getter / Setter
     *
     * **************************************************************************************
     * */

    public boolean isEnableExtend() {
        return enableExtend;
    }

    public void setEnableExtend(Boolean enableExtend) {
        this.enableExtend = enableExtend != null;
    }

    public TimePair getMaxAllowExtendTime() {
        return maxAllowExtendTime;
    }

    public void setMaxAllowExtendTime(TimePair maxAllowExtendTime) {
        this.maxAllowExtendTime = maxAllowExtendTime;
    }

    public void setMaxAllowExtendTime(long maxAllowExtendTime, Timeunit timeunit) {
        this.maxAllowExtendTime = new TimePair(maxAllowExtendTime, timeunit);
    }

    public int getMaxAllowCount() {
        return maxAllowCount;
    }

    public void setMaxAllowCount(int maxAllowCount) {
        this.maxAllowCount = maxAllowCount;
    }

    public TimePair getExtendTime() {
        return extendTime;
    }

    public void setExtendTime(TimePair extendTime) {
        this.extendTime = extendTime;
    }

    public void setExtendTime(long extendTime, Timeunit timeunit) {
        this.extendTime = new TimePair(extendTime, timeunit);
    }

    public TimePair getMinExtendThresholdTime() {
        return minExtendThresholdTime;
    }

    public void setMinExtendThresholdTime(TimePair minExtendThresholdTime) {
        this.minExtendThresholdTime = minExtendThresholdTime;
    }

    public void setMinExtendThresholdTime(long minExtendThresholdTime, Timeunit timeunit) {
        this.minExtendThresholdTime = new TimePair(minExtendThresholdTime, timeunit);
    }

    @Note("是否满足了前两个必须条件。只有这个方法的返回值为 true，" +
            "maxAllowExtendTime 或 maxAllowCount 的开启才会有效")
    public boolean isAllowedExtend() {
        if(!enableExtend) return false;
        if(extendTime == null) return false;
        return extendTime.getSourceTime() > 0;
    }

    @Note("是否使用 maxAllowExtendTime 策略")
    public boolean isUseMaxAllowExtendTime() {
        if(maxAllowExtendTime == null) return false;
        return maxAllowExtendTime.getSourceTime() > 0;
    }

    @Note("是否使用 maxAllowCount 策略")
    public boolean isUseMaxAllowCount() {
        return maxAllowCount > 0;
    }

    @Override
    public String toString() {
        return "TokenExtender{" +
                "enableExtend=" + enableExtend +
                ", extendTime=" + extendTime +
                ", maxAllowExtendTime=" + maxAllowExtendTime +
                ", maxAllowCount=" + maxAllowCount +
                ", minExtendThresholdTime=" + minExtendThresholdTime +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TokenExtender that = (TokenExtender) o;
        return enableExtend == that.enableExtend && maxAllowCount == that.maxAllowCount && Objects.equals(extendTime, that.extendTime) && Objects.equals(maxAllowExtendTime, that.maxAllowExtendTime) && Objects.equals(minExtendThresholdTime, that.minExtendThresholdTime);
    }

    @Override
    public int hashCode() {
        return Objects.hash(enableExtend, extendTime, maxAllowExtendTime, maxAllowCount, minExtendThresholdTime);
    }


    public TokenExtender enableExtend(Boolean enableExtend) {
        this.setEnableExtend(enableExtend);
        return this;
    }

    public TokenExtender extendTime(TimePair extendTime) {
        this.setExtendTime(extendTime);
        return this;
    }

    public TokenExtender extendTime(long extendTime, Timeunit timeunit) {
        this.setExtendTime(extendTime, timeunit);
        return this;
    }

    public TokenExtender maxAllowExtendTime(TimePair maxAllowExtendTime) {
        this.setMaxAllowExtendTime(maxAllowExtendTime);
        return this;
    }

    public TokenExtender maxAllowExtendTime(long maxAllowExtendTime, Timeunit timeunit) {
        this.setMaxAllowExtendTime(maxAllowExtendTime, timeunit);
        return this;
    }

    public TokenExtender maxAllowCount(int maxAllowCount) {
        this.setMaxAllowCount(maxAllowCount);
        return this;
    }

    public TokenExtender minExtendThresholdTime(TimePair minExtendThresholdTime) {
        this.setMinExtendThresholdTime(minExtendThresholdTime);
        return this;
    }

    public TokenExtender minExtendThresholdTime(long minExtendThresholdTime, Timeunit timeunit) {
        this.setMinExtendThresholdTime(minExtendThresholdTime, timeunit);
        return this;
    }
}
